package softsdk

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"fmt"
	"os"
	"strings"
)

var (
	pAesSK []byte
)

func AesEncUtf8(utf8ClearText string) ([]byte, error) {
	return aesEncCore([]byte(utf8ClearText))
}

func AesDecUtf8(utf8EncText []byte) (string, error) {
	plainTextBytes, err := aesDecCore(utf8EncText)
	if err != nil {
		return "", err
	}
	return string(plainTextBytes), nil
}

// AesEncS32Ex 批量加密int32
func AesEncS32Ex(int32Arr []int32) ([][]byte, error) {
	res := make([][]byte, 0)
	for _, plain := range int32Arr {
		enc, err := AesEncS32(plain)
		if err != nil {
			return nil, err
		}
		res = append(res, enc)
	}
	return res, nil
}

// AesEncS32 加密单个int32
func AesEncS32(plain int32) ([]byte, error) {
	plainBytes := int32ToBytes(plain)
	return aesEncCore(plainBytes)
}

func AesDecS32(encData []byte) (int32, error) {
	plainBytes, err := aesDecCore(encData)
	if err != nil {
		return 0, err
	}
	return bytesToInt32(plainBytes), nil
}

func int32ToBytes(num int32) []byte {
	// 大端序存储，即高位字节存储在低地址位置
	result := make([]byte, 4)
	result[0] = byte(num >> 24)
	result[1] = byte(num >> 16)
	result[2] = byte(num >> 8)
	result[3] = byte(num)
	return result
}

func bytesToInt32(buf []byte) int32 {
	num := int32(buf[0])<<24 | int32(buf[1])<<16 | int32(buf[2])<<8 | int32(buf[3])
	return num
}

func readAesEncSK(filePath string) error {
	aesSkBytes, err := os.ReadFile(filePath)
	if err != nil {
		return fmt.Errorf("unable to open aes secret key file")
	}
	aesSkStr := strings.Replace(string(aesSkBytes), "\r", "", -1)
	aesSkLines := strings.Split(aesSkStr, "\n")
	if len(aesSkStr) == 0 {
		return fmt.Errorf("error: aes_sk loading failed-1")
	}
	aesSkLine := aesSkLines[0]
	aesSk, err := hex.DecodeString(aesSkLine)
	if err != nil {
		return fmt.Errorf("error: aes_sk loading failed-2")
	}
	if len(aesSk) != 16 {
		return fmt.Errorf("error: aes_sk loading failed-3")
	}
	pAesSK = aesSk
	return nil
}

func aesEncCore(data []byte) ([]byte, error) {
	if pAesSK == nil {
		return nil, fmt.Errorf("aes_sk not load")
	}
	// 创建一个新的 AES 加密块
	block, err := aes.NewCipher(pAesSK)
	if err != nil {
		panic(err)
	}
	// 生成一个初始向量 (IV)，长度等于 AES 块大小
	iv := []byte("1234567890123456") // 示例固定IV，必须是16字节
	// 使用 CBC 模式包装加密块
	stream := cipher.NewCFBEncrypter(block, iv)
	// 创建一个与明文长度相同的密文切片
	cipherText := make([]byte, len(data))
	// 加密数据
	stream.XORKeyStream(cipherText, data)
	// 将 IV 附加到密文前面，以便在解密时使用
	result := make([]byte, aes.BlockSize+len(cipherText))
	copy(result, iv)
	copy(result[aes.BlockSize:], cipherText)
	return result, nil
}

func aesDecCore(data []byte) ([]byte, error) {
	if pAesSK == nil {
		return nil, fmt.Errorf("aes_sk not load")
	}
	// 创建一个新的 AES 加密块
	block, err := aes.NewCipher(pAesSK)
	if err != nil {
		panic(err)
	}
	// 提取 IV
	iv := data[:aes.BlockSize]
	cipherText := data[aes.BlockSize:]
	// 使用 CBC 模式包装加密块
	stream := cipher.NewCFBDecrypter(block, iv)
	// 创建一个与密文长度相同的明文切片
	plainText := make([]byte, len(cipherText))
	// 解密数据
	stream.XORKeyStream(plainText, cipherText)
	return plainText, nil
}
